﻿using System;
using System.Collections;
using Rpg.UI;
using UnityEngine;

public class ControllerBase:MonoBehaviour
{
    #region Component
    public Animator mAnimator { get;private set; }
    public Rigidbody2D mRigidbody2D{ get;private set; }
    public Collider2D mCollider2D{ get;private set; }
    public FlashFX flashFX{ get; private set; }
    
    public CharacterBase characterBase{ get; protected set; }
    
    public SpriteRenderer mSpriteRenderer{ get; private set; }
    
    public EntityStatUI entityStatUI{ get; private set; }
    #endregion
    
    
    [SerializeField]protected Transform groundCheck;
    [SerializeField]protected Transform wallCheck;
    [SerializeField]protected Transform attackCheck;
    
    public bool isGround;
    public bool isWall;
    
    //默认面向右
    public bool isFacingRight = true;
    public int faceDir = 1;
    
    //防止某些状态快速切换
    public bool isBusy;

    //是否被击退
    public bool isKnockBack;
    
    public void StartBusy(float sec)
    {
        StartCoroutine(IsBusy(sec));
    }
    
    public IEnumerator IsBusy(float sec)
    {
        isBusy = true;
        yield return new WaitForSeconds(sec);
        isBusy = false;
    }
    
    
    #region 状态机

    public  StateMachineBase stateMachine{get; protected set; }
    
    protected virtual void InitStates()
    {
        stateMachine = new StateMachineBase();
        /*stateMachine.AddState(new PlayerIdleState(this, stateMachine,
            Setting.idle,Setting.AnimatorIdle));
        stateMachine.AddState(new PlayerMoveState(this, stateMachine,
            Setting.move, Setting.AnimatorMove));
        stateMachine.AddState(new PlayerDashState(this, stateMachine,
            Setting.dash, Setting.AnimatorDash));
        stateMachine.AddState(new PlayerJumpState(this, stateMachine,
            Setting.jump, Setting.AnimatorJump));
        stateMachine.AddState(new PlayerAirState(this, stateMachine,
            Setting.air, Setting.AnimatorJump));
        stateMachine.AddState(new PlayerWallSlide(this, stateMachine,
            Setting.wallSlide, Setting.AnimatorWallSlide));
        stateMachine.AddState(new PlayerWallJump(this, stateMachine,
            Setting.wallJump, Setting.AnimatorJump));
        stateMachine.AddState(new PlayerPrimaryAttack(this,stateMachine,
            Setting.primaryAttack, Setting.AnimatorAttack));*/
    }
    
    
    #endregion

    #region 初始化数值
    protected  virtual void InitStats()
    {
        characterBase = new CharacterBase(transform.gameObject.name,this);
        
        characterBase.OnFireStatusStart += OnFireStatusStart;
        characterBase.OnFireStatusEnd += OnFireStatusEnd;
        characterBase.OnIceStatusStart += OnIceStatusStart;
        characterBase.OnIceStatusEnd += OnIceStatusEnd;
        characterBase.OnElectricStatusStart += OnElectricStatusStart;
        characterBase.OnElectricStatusEnd += OnElectricStatusEnd;
    }
    
    #endregion
    
    protected virtual void Awake()
    {
        mAnimator = GetComponentInChildren<Animator>();
        mSpriteRenderer = GetComponentInChildren<SpriteRenderer>();
        mRigidbody2D = GetComponent<Rigidbody2D>();
        flashFX = GetComponent<FlashFX>();
        mCollider2D = GetComponent<Collider2D>();
        entityStatUI =  GetComponentInChildren<EntityStatUI>();
    }

    protected virtual void  Start()
    {
        InitStats();
        InitStates();
        stateMachine.Start();
    }
    
    protected virtual void Update()
    {
        // 检查是否在地面
        CheckGround();
        // 检查贴着墙
        CheckWall();
        SetYVelocity();
        stateMachine.Update();

        if (characterBase!=null)
        {
            characterBase.Update();
        }
    }

    
    
    #region Velocity

    public void SetVelocity(Vector2 velocity)
    {
        if (isKnockBack)
        {
            return;
        }
        mRigidbody2D.velocity = velocity;
        FlipController(velocity.x);
    }

    public Vector2 GetVelocity()
    {
        return mRigidbody2D.velocity;
    }

    #endregion

    #region 翻转

    public Action OnFlip;//翻转
    public void FlipController(float x)
    {
        if (x < 0 && isFacingRight || x > 0 && !isFacingRight)
        {
            Flip();
        }
    }
        
    public void Flip()
    {
        isFacingRight = !isFacingRight;
        faceDir = -faceDir;
        transform.eulerAngles = new Vector3(0, isFacingRight ? 0 : 180, 0);
        OnFlip?.Invoke();
    }
    

    #endregion

    #region 物理检测

    private void CheckGround()
    {
        isGround = Physics2D.OverlapCircle(groundCheck.position, 
            Setting.groundCheckRadius,
            LayerMask.GetMask("Ground"));
    }

    private void CheckWall()
    {
        isWall = Physics2D.Linecast(wallCheck.position,
            wallCheck.position + Vector3.right * faceDir * Setting.wallCheckLine,
            LayerMask.GetMask("Ground"));
    }
    

    #endregion
    
    #region Animator
    
    private void SetYVelocity()
    {
        mAnimator.SetFloat(Setting.Yvelocity, mRigidbody2D.velocity.y);
    }

    #endregion

    #region 伤害
    
    public float GetDamage()
    {
        return characterBase.GetValue(StatType.Damage);
    }
    
    public void Damage(DamgeInfo info)
    {
        if (characterBase.IsDead())
        {
            return;
        }
        var damageResult = characterBase.DoDamage(info);

        if (characterBase.IsDead())
        {
            //GoDead();
            return;
        }
        //伤害表现
        DamageReaction(info, damageResult);
    }

    public void GoDead()
    {
        Debuger.LogRed($"{transform.name}死亡了");
        //清理掉他身上的所有协程
        StopAllCoroutines();
        //进入死亡状态
        stateMachine.ChangeState(Setting.dead);
    }
    
    private void DamageReaction(DamgeInfo info, DamegResult damageResult)
    {
        if (damageResult.isDefend)
        {
            //TODO:防御表现:防御音效
            //被防御无法击退
            info.hitBackForce = Vector2.zero;
        }
        //闪烁
        FlashFx();
        //击退
        if (info.hitBackForce!=Vector2.zero)
        {
            HitBack(info.hitBackForce,info.hitBackTime);
        }
    }

    public void FlashFx(float sec = 0.2f)
    {
        flashFX.TriggerFlash(sec);
    }
    //击退
    protected virtual void HitBack(Vector2 hitForce, float sec = 0.2f)
    {
        StartCoroutine(KnockBack(hitForce,sec));
    }
    
    private IEnumerator KnockBack(Vector2 hitForce, float sec = 0.2f)
    {
        isKnockBack = true;
        mRigidbody2D.AddForce(hitForce, ForceMode2D.Impulse);
        yield return new WaitForSeconds(sec);
        isKnockBack = false;
    }
    
    //强制击退
    public void ForceHitBack(Vector2 hitForce)
    {
        HitBack(hitForce);
    }
    //强制冻结或者解冻
    public void ForceForzen(bool isFrozen,float sec = 0)
    {
        characterBase.ForceFrozen(isFrozen,sec);
        mRigidbody2D.velocity = Vector2.zero;
        mAnimator.speed = characterBase.IsFrozen() ? 0 : 1;
    }
    
    public Vector2 GetAttackCheckPos()
    {
        return attackCheck.position;
    }

    public bool IsDead()
    {
        return characterBase.IsDead();
    }
    
    public bool IsFrozen()
    {
        return characterBase.IsFrozen();   
    }
    
    #endregion
    #region 异常事件
    private void OnElectricStatusEnd()
    {
        flashFX.StopLightning();
    }

    private void OnElectricStatusStart()
    {
        //变黄
        flashFX.TriggerLightning();
    }

    private void OnIceStatusEnd()
    {
        mAnimator.speed = 1;
        flashFX.StopIce();
    }

    private void OnIceStatusStart()
    {
        mAnimator.speed = 0;
        flashFX.TriggerIce();
    }

    private void OnFireStatusEnd()
    {
        flashFX.StopFire();
    }

    private void OnFireStatusStart()
    {
        //变红
        flashFX.TriggerFire();
    }

    private void OnDisable()
    {
        
        characterBase.OnFireStatusStart -= OnFireStatusStart;
        characterBase.OnFireStatusEnd -= OnFireStatusEnd;
        characterBase.OnIceStatusStart -= OnIceStatusStart;
        characterBase.OnIceStatusEnd -= OnIceStatusEnd;
        characterBase.OnElectricStatusStart -= OnElectricStatusStart;
        characterBase.OnElectricStatusEnd -= OnElectricStatusEnd;
        
    }

    #endregion
    
    public void HideOrShowSelf(bool isHide)
    {
        mSpriteRenderer.color = new Color(mSpriteRenderer.color.r,mSpriteRenderer.color.g,mSpriteRenderer.color.b,isHide?0:1);
        entityStatUI.gameObject.SetActive(!isHide);
    }
    
    protected virtual void OnDrawGizmos()
    {
        Gizmos.color = Color.red;
        if (groundCheck!=null)
        {
            Gizmos.DrawSphere(groundCheck.position, Setting.groundCheckRadius);
        }

        if (wallCheck != null)
        {
            Gizmos.DrawLine(wallCheck.position, wallCheck.position + Vector3.right * faceDir * Setting.wallCheckLine);
        }
        
    }
}